<!--用户管理页面-->
<template>
  <!--  一、用户管理文字和新增用户按钮  -->
  <div style="height:6vh; background-color: #fff;padding: 10px 20px">
    <!--  为了让"用户管理"文字和 "新增用户" 按钮不要挤到面包屑的位置，就需要给div设置样式 (内边距) -->
    <!--  上边的div设置样式之后，div高度为6vh,宽度会占满右侧的页面主体区域，背景色是白色。
    为了让上边的折叠菜单的图标和此div风格保持一致，则给HomeView.vue中的折叠图标和登录用户名所在的el-header也设置背景色 #fff -->
    <span style="font-size: 20px;line-height: 60px;">用户管理</span>
    <el-button  @click="dialogVisible=true" type="primary" style="float: right;margin-top: 10px;">新增用户</el-button> <!-- 按钮需要居右 -->
  </div>

  <!-- 二、新建/编辑用户弹窗 。  before-close="handleCloseMethod"表示弹窗关闭之前先执行handleCloseMethod()方法进行确认(避免点击弹窗外部也关闭弹窗)-->
  <!--  通过:title="dialogTitle"来设置此弹窗左上角显示的标题(是 新增用户还是编辑用户)  -->
  <el-dialog :title="dialogTitle"  v-model="dialogVisible" :before-close="handleCloseMethod" style="width: 1000px;padding: 40px;" >
    <el-form label-position="top" label-width="80px"> <!--label-position="top"是让表单项的文字居于表单项的上方-->
      <el-row :gutter="30">
        <el-col :span="12">  <!--一行两个表单项，所以左右各占12份  (v-model是双向绑定)-->
          <el-form-item label="用户名">
            <el-input placeholder="请输入用户名" v-model="saveUserForm.username" :disabled="saveUserForm.id!=null"></el-input>
          </el-form-item>  <!-- :disabled="saveUserForm.id!=null" 表示用户id不为空时就禁用此用户  -->
        </el-col>
        <el-col :span="12">
          <el-form-item label="手机号">
            <el-input placeholder="请输入手机号" v-model="saveUserForm.phone"></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <!--  第二行-->
      <el-row :gutter="30">
        <el-col :span="12">  <!--  一行两个表单项，所以左右各占12份  -->
          <el-form-item label="邮箱">
            <el-input placeholder="请输入邮箱" v-model="saveUserForm.email"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="年龄" >
            <el-input placeholder="请输入年龄" v-model="saveUserForm.age"></el-input>
          </el-form-item>
        </el-col>
      </el-row>

      <!--  第二行  -->
      <el-row :gutter="30">
        <el-col :span="6">  <!-- 本行左侧 有两个表单项，所以两个各占6份-->
          <el-form-item label="职级" >
            <el-select placeholder="请选择职级" v-model="saveUserForm.level" @change="loadLeader">
              <!--   需要让职级跟随数据库的改变而改变，所以从数组中取出数据来用v-for显示  :label="item.label"是属性绑定  -->
              <el-option v-for="item in levelOptions" :label="item.label" :value="item.value"></el-option>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="6">  <!-- 本行左侧 有两个表单项，所以两个各占6份-->
          <el-form-item label="直属领导" >
            <el-select placeholder="请选择直属领导" v-model="saveUserForm.parentId">
              <el-option v-for="item in leaderOptions" :label="item.username" :value="item.id"></el-option>
            </el-select>
          </el-form-item>
        </el-col>

        <el-col :span="4">  <!--  想让性别和用户状态离得近一些(如果性别占6列，则性别单选按钮就会太大了) -->
          <!-- 本占4列， 当前列占4份儿,但是el-radio的右margin是32px左右太大了男女放不到一行，所以要修改男对应的el-radio的外边距-->
          <el-form-item label="性别">
            <el-radio-group v-model="saveUserForm.gender">
              <el-radio label="男" style="margin: 0;" border value="1"></el-radio> <!-- border是用于给单选按钮添加边框 -->
              <el-radio label="女" border value="0"></el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <!-- 本占4列， 当前列占4份儿,但是el-radio的右margin是32px左右太大了男女放不到一行，所以要修改男对应的el-radio的外边距-->
          <el-form-item label="用户状态">
            <el-radio-group v-model="saveUserForm.status">
              <el-radio label="启用" style="margin: 0;" border value="1"></el-radio> <!-- border是用于给单选按钮添加边框 -->
              <el-radio label="禁用" border value="0"></el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>


      </el-row>
    </el-form>


    <template #footer> <!--  template表示插槽，具体指的是template是自定义的内容，#footer表示此插槽属于弹窗的尾部。  -->

      <div class="dialog-footer">
        <el-button @click="handleCloseMethod">取消</el-button>
        <el-button type="primary" @click="saveOrUpdateUser">
          保存
        </el-button>
      </div>
    </template>
  </el-dialog>





  <!--  三、用户查询卡片的小区域   :inline="true" 表示让表单项横向放置(横置) -->
  <!--  卡片高度太高了，而且和左侧挨着呢。 所以要设置样式 style="margin:20px; height: 70px"  -->
  <el-card style="margin:20px; height: 70px">
    <el-form :inline="true">
      <el-form-item label="用户搜索">
        <el-input placeholder="请输入用户名" style="width: 220px;"
                  v-model="searchUserForm.username" @keydown.enter="loadUsers"></el-input>
      </el-form-item>   <!--  v-model="searchUserForm.username"用于将此组件和下边的searchUserForm的值进行双向绑定，
      主要是让点击组件后来修改下边searchUserForm的值  -->

      <el-form-item label="用户状态">
        <el-select placeholder="请选择用户状态"  style="width: 290px;"
                   v-model="searchUserForm.status"  @change="loadUsers">
          <el-option label="启用" value="1"></el-option>
          <el-option label="禁用" value="0"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button @click="resetSearch">重置</el-button>
        <el-button type="primary" @click="loadUsers">查询</el-button>
      </el-form-item>

    </el-form>
  </el-card>




  <!-- 四、用户列表信息表格 -->
  <!--  卡片和左侧挨着呢。 所以要设置样式 style="margin:20px;"(可以和上边的用户查询卡片区域左对齐)  -->
  <el-card style="margin:20px;">
    <el-table :data="userArr">
      <el-table-column type="index" label="编号" width="80" align="center"></el-table-column>
      <el-table-column prop="username" label="用户名"  align="center"></el-table-column><!-- prop="username"表示从对象中取出username显示 --><!--  -->
      <el-table-column prop="phone" label="手机号"  align="center"></el-table-column><!--  -->
      <el-table-column prop="createTime" label="添加时间"  align="center"></el-table-column><!--  -->
      <el-table-column prop="status" label="用户状态" align="center">
        <template #default="scope">  <!-- 如果不是文字的话需要用template包含。  v-model是双向绑定. scope.row是当前行对象-->
          <el-switch v-model="scope.row.status" active-value="1" inactive-value="0"
                     :disabled="scope.row.level==40"  @change="changeStatus(scope.row.id, scope.row.status)">
            <!--  :disabled="scope.row.level==40"表示如果用户职级是40(总裁)则不能修改状态  -->
          </el-switch> <!-- el-switch是开关组件， 开关模式支持boolean类型的值 -->
        </template>  <!-- 相当于取出v-model中的值判断，如果是1则满足 active-value="1"表示开关打开， 是0则满足 inactive-value="0"表示开关关闭
                   el-switch v-model="num" :active-value="1" :inactive-value="0"-->
        <!-- :active-value="1"数字1表示开关打开 :inactive-value="0"数字0表示开关关闭 -->
      </el-table-column>
      <el-table-column label="操作" align="center">
        <template #default="scope"> <!--  link用于将按钮设置为链接按钮  -->
          <el-button type="primary" size="mini" @click="editUser(scope.row.id)" link  :disabled="scope.row.level==40">修改</el-button>
          <el-button type="primary" size="mini" @click="resetPwd(scope.row.id)" link  :disabled="scope.row.level==40">密码重置</el-button>
          <el-button type="danger" size="mini" @click="delUser(scope.row.id)" link  :disabled="scope.row.level==40">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-card>

</template>


<style scoped>
/**为了让页面的主体内容有一个背景色(且每个独立的页面都会有同样的背景色)，所以在App.vue中设置一个背景色*/
</style>

<script setup>
// setup 表示js的一种写法
import {onMounted, ref} from 'vue';

import axios  from "axios";
import {ElMessage} from "element-plus";
import qs from "qs"

//定义变量用来控制弹窗是否显示
const dialogVisible=ref(false);
//定义变量用来保存弹窗的标题
const dialogTitle=ref('新建用户');  //因为修改用户和新增用户要采用同一个弹窗页面。

//定义对象收集新增/修改员工弹窗的表单信息
const saveUserForm = ref({
  username:'',
  phone:'',
  email:'',
  age:'',
  level:'',
  parentId:'',
  gender:'1',
  status:'1'
});

//定义数组保存员工职级选项(响应式数组)//后边要和数据库保持一致
const levelOptions = ref([
  {label:'职员',value:'10'},
  {label:'经理',value:'20'},
  {label:'总监',value:'30'},
  {label:'总裁',value:'40'}
]);

//定义数组保存直属领导数据//后边要和数据库保持一致
const leaderOptions = ref([
  {username:'shaoyun',id:'1'},
  {username:'mike',id:'2'}
]);

//定义获取直属领导数据的方法loadLeader()， 用于在新增用户时选择他的直属领导
const loadLeader= ()=>{
  //优化:如果已经勾选了直属领导,想再重新选择职级的话,需要将之前的直属领导数组与已选择的直属领导数据清空
  leaderOptions.value=[];
  saveUserForm.value.parentId='';
  //拿到当前用户选择的职级:  当前用户的职级+10为直属领导的职级
  let level=parseInt(saveUserForm.value.level)+10;//注意：需要将获取到的saveUserForm的level转为number类型(否则就是字符串的拼接)
  //给后端发请求查数据
  axios.get(BASE_URL+'/v1/user/selectUsers?level=' + level).then( (response)=>{
    if(response.data.code==2000){
      leaderOptions.value=response.data.data;
    }else{
      ElMessage.error(response.data.msg);
    }
  });
};

const saveOrUpdateUser =  ()=>{
  //console.log(saveUserForm.value);
  //为了方便使用baseurl，所以将baseurl保存main.js的BASEURL中
  axios.post(BASE_URL+'/v1/user/save' ,saveUserForm.value).then(
    (response)=>{
       if(response.data.code==2000){
         ElMessage.success(response.data.msg);
         //ElMessage.success('保存成功!');
         dialogVisible.value=false;//保存成功后，关闭弹窗
         //清空已入库的表单数据，否则再次打开弹窗还是之前的值
         saveUserForm.value={};
         //新增/更新用户后,都需要重新加载所有用户数据(用于显示新增或修改后的数据)
         loadUsers();
       }else{
         ElMessage.error(response.data.msg);
       }
    }
  );
};

//定义处理弹窗关闭的方法
const handleCloseMethod= ()=>{
  //1.确认是否关闭
  if(confirm('确定关闭本窗口吗？')){
    //用户如果确认关闭，就关闭弹窗
    dialogVisible.value=false;
    //清空已输入的表单数据
    saveUserForm.value={};
  }
};


//定义数组用来保存用户列表数据//因为userArr数组是响应式的对象，所以必须要用 userArr.value的格式去使用
const userArr= ref([
  {username:'ss',phone:'18811112222',createTime:'2022-01-01',status:'1'},
  {username:'yy',phone:'18811113333',createTime:'2022-03-03',status:'0'}
]);

//定义对象用来保存按条件查询用户的查询条件
const searchUserForm=ref({username:'',status:''});

//定义加载所有用户数据的方法loadUsers()， 用于在用户列表页面显示
const loadUsers=  ()=>{
  let data= qs.stringify(searchUserForm.value);//将js对象转化为json字符串
  console.log(data);
  //如果有查询条件,就根据条件查,没有查询条件,默认查全部员工信息 //? + data 是一种restful风格的写法。
  axios.get( BASE_URL+'/v1/user/selectUsers?' + data).then(
      (response)=>{
        //如果后端返回的状态码是2000,说明成功了
        if(response.data.code==2000){
          //把成功请求回来的数据装到与表格绑定的数组中
          userArr.value=response.data.data;//因为userArr数组是响应式的对象，所以必须要用 userArr.value的格式去使用
        }else{
          ElMessage.error(response.data.msg);
        }
      }
  );
};

//定义重置搜索信息的响应式函数
const resetSearch= ()=>{
  //清空之前输入的搜索内容
  searchUserForm.value={};
  //重新加载所有的用户数据
  loadUsers();
};

//修改员工状态
const changeStatus= (userId, status)=>{
  axios.post(BASE_URL+'/v1/user/updateStatus/' + userId +'/'+status).then(
      (response)=>{
        if(response.data.code==2000){
          ElMessage.success('状态修改成功');
        }else{
          ElMessage.error(response.data.msg);
          //如果数据库没修改成功的话，需要将页面当前用户的状态s
          //刷新为修改前的状态，也就是重新加载下用户列表即可
          loadUsers();
        }
      }
  );
};

const delUser= (userId)=>{
  axios.get(BASE_URL+'/v1/user/deleteUser/' + userId).then( (response)=>{
    if(response.data.code==2000){
      ElMessage.success('删除用户成功');
      loadUsers();//删除用户成功之后，要从mysql重新加载所有的用户数据
    }else{
      ElMessage.error(response.data.msg);
    }
  });
};


//定义用于修改用户信息时， 将用户信息查询并显示到弹窗表单中的响应式方法editUser()
//加载后在表单中提交，提交后通过公用新增用户的方法saveOrUpdateUser()来完成修改操作
const editUser= (userId)=>{
  //1.打开弹窗并修改标题
  dialogVisible.value=true;//dialogVisible是一个响应式变量，所以要写成dialogVisible.value
  dialogTitle.value='修改用户';//修改标题
  //2.用axios给后端发请求/v1/user/selectUsers?id=userId根据userId查询要修改的员工信息
  axios.get(BASE_URL+'/v1/user/selectUsers?id='+userId).then( (response)=>{
    if(response.data.code==2000){
      //2.1.从查询结果中取出要修改的员工信息赋值给表单要显示的对象saveUserForm中
      //注意:后端返回的是List<UserVO> list! 所以这里是data[0]
      saveUserForm.value=response.data.data[0];
      //2.2.获取可选直属领导数据//查询要修改的员工数据后，立即查询此员工的直属领导数据(用于显示到页面上以供修改)
      let level=parseInt(saveUserForm.value.level)+10;
      //用axios给后端发请求'/v1/user/select?level=level，查数据
      axios.get(BASE_URL+'/v1/user/selectUsers?level='+level).then( (response)=>{
        if(response.data.code==2000){
          leaderOptions.value=response.data.data;
        }else{
          ElMessage.error(response.data.msg);
        }
      });

    }else{
      ElMessage.error(response.data.msg);
    }
  });
};

//定义重置密码的函数resetPwd()   //'/v1/user/resetPwd/'+userId   是restful风格的写法
const resetPwd= (userId)=>{
  axios.post(BASE_URL+'/v1/user/resetPwd/'+userId).then( (response)=>{
    if(response.data.code==2000){
      ElMessage.success('密码重置成功!');
    }else{
      ElMessage.error(response.data.msg);
    }
  });
};

//一进入到页面就执行onMouted()方法，
//onMouted()是一个生命周期方法，表示页面刚加载完就执行的方法
//给它里边设置一个回调函数并在回调函数中调用loadUsers();
//用来在页面一加载时查询所有用户数据
onMounted(
    ()=>{
      loadUsers();//加载所有员工数据
    }
);

</script>